package kr.pe.silent.etweeter.views;

import com.swtdesigner.ResourceManager;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;

import twitter4j.Status;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class TweetItem extends Composite {

	private Label lblProfileImage;
	private StyledText txtProfileName;
	private StyledText txtStatusText;
	private StyledText txtTime;
	private StyledText txtFunction;

	/**
	 * Create the composite.
	 * @param parent
	 * @param style
	 */
	public TweetItem(Composite parent, int style) {
		super(parent, style);
		setBackground(ResourceManager.getColor(SWT.COLOR_LIST_BACKGROUND));
		GridLayout gridLayout = new GridLayout(3, false);
		gridLayout.marginWidth = 10;
		gridLayout.marginHeight = 10;
		gridLayout.verticalSpacing = 0;
		gridLayout.horizontalSpacing = 10;
		setLayout(gridLayout);

		lblProfileImage = new Label(this, SWT.NONE);
		lblProfileImage.setBackground(ResourceManager.getColor(SWT.COLOR_LIST_BACKGROUND));
		lblProfileImage.setImage(ResourceManager.getPluginImage("kr.pe.silent.etweeter", "icons/etweeter1.png"));
		GridData gd_lblProfileImage = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 3);
		gd_lblProfileImage.heightHint = 48;
		gd_lblProfileImage.widthHint = 48;
		lblProfileImage.setLayoutData(gd_lblProfileImage);

		txtProfileName = new StyledText(this, SWT.NONE);
		txtProfileName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		txtStatusText = new StyledText(this, SWT.WRAP);
		txtStatusText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
		txtStatusText.addListener(SWT.MouseDown, new Listener() {
            public void handleEvent(Event event) {
                try {
                    int offset = txtStatusText.getOffsetAtLocation(new Point(event.x, event.y));
                    StyleRange style = txtStatusText.getStyleRangeAtOffset(offset);
                    if (style != null && style.underline
                            && style.underlineStyle == SWT.UNDERLINE_LINK) {
                        openBrowser((String)style.data);
                    }
                } catch (IllegalArgumentException e) {
                    // no character under event.x, event.y
                }
            }
        });

		txtTime = new StyledText(this, SWT.NONE);

		txtFunction = new StyledText(this, SWT.NONE);
		txtFunction.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

	}

	public void setStatus(Status status) {
	    // icon
		try {
			lblProfileImage.setImage(new Image(getDisplay(), status.getUser().getProfileImageURL().openStream()));
		} catch (IOException e) {
		}
		
		// name
		String screenName = status.getUser().getScreenName();
		String name = status.getUser().getName();
		txtProfileName.setText(screenName + " " + name);
		StyleRange rangeBold = new StyleRange();
		rangeBold.start = 0;
		rangeBold.length = screenName.length();
		rangeBold.fontStyle = SWT.BOLD;
		StyleRange rangeGray = new StyleRange();
		rangeGray.start = screenName.length() + 1;
		rangeGray.length = name.length();
		rangeGray.foreground = ResourceManager.getColor(SWT.COLOR_GRAY);
		txtProfileName.setStyleRanges(new StyleRange[] {rangeBold, rangeGray});
		
		// message
		String message = status.getText();
        txtStatusText.setText(message);
        txtStatusText.setStyleRanges(getStyleRangesForMessage(message));
		
		// time
		String timeMessage = getTimeMessage(status.getCreatedAt());
		txtTime.setText(timeMessage);
		rangeGray.start = 0;
		rangeGray.length = timeMessage.length();
		txtTime.setStyleRange(rangeGray);

		layout();
	}

    private StyleRange[] getStyleRangesForMessage(String message) {
        int length = message.length();
        int fromIndex = 0;
        int endIndex = 0;
        ArrayList<StyleRange> ranges = new ArrayList<StyleRange>();

        for (fromIndex = 0; fromIndex < length; fromIndex = endIndex + 1) {
            fromIndex = message.indexOf("http://t.co/", fromIndex);
            if (fromIndex != -1) {
                endIndex = fromIndex + 20;
                ranges.add(createLinkStyleRange(fromIndex, 20, message.substring(fromIndex, endIndex)));
            } else {
                break;
            }
        }
        
        for (fromIndex = 0; fromIndex < length; fromIndex = endIndex + 1) {
            fromIndex = message.indexOf('#', fromIndex);
            if (fromIndex != -1) {
                endIndex = message.indexOf(' ', fromIndex + 1);
                if (endIndex == -1) endIndex = length;
                ranges.add(createLinkStyleRange(fromIndex, endIndex - fromIndex, message.substring(fromIndex, endIndex)));
            } else {
                break;
            }
        }
        
        for (fromIndex = 0; fromIndex < length; fromIndex = endIndex + 1) {
            fromIndex = message.indexOf('@', fromIndex);
            if (fromIndex != -1) {
                endIndex = message.indexOf(' ', fromIndex + 1);
                if (endIndex == -1) endIndex = length;
                ranges.add(createLinkStyleRange(fromIndex, endIndex - fromIndex, message.substring(fromIndex, endIndex)));
            } else {
                break;
            }
        }

        if (ranges.size() > 1) {
            Collections.sort(ranges, new Comparator<StyleRange>() {
                @Override
                public int compare(StyleRange o1, StyleRange o2) {
                    return o1.start - o2.start;
                }
            });
        }
        return ranges.toArray(new StyleRange[ranges.size()]);
    }

	private StyleRange createLinkStyleRange(int start, int length, String text) {
	    StyleRange range = new StyleRange();
	    range.start = start;
	    range.length = length;
	    range.underline = true;
	    range.underlineStyle = SWT.UNDERLINE_LINK;
	    range.data = text;
	    return range;
	}

    private String getTimeMessage(Date createAt) {
		long current = System.currentTimeMillis();
		long create = createAt.getTime();

		long diffSec = (current - create) / 1000;
		if (diffSec < 60) {
			// sec
			return diffSec + "s";
		} else if (diffSec < 3600) {
			// min
			return (diffSec / 60) + "m";
		} else if (diffSec < 3600 * 24) {
			// hour
			return (diffSec / 60 * 24) + "h";
		} else {
			// day
			return (diffSec / 3600 * 24) + "d";
		}
	}

    private void openBrowser(String data) {
        try {
            IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
            IWebBrowser browser = support.createBrowser(null);
            browser.openURL(getURL(data));
        } catch (PartInitException e) {
        } catch (MalformedURLException e) {
        }
    }

    private URL getURL(String text) throws MalformedURLException {
        if (text.startsWith("http")) {
            return new URL(text);
        } else if (text.startsWith("#")) {
            return new URL("http://twitter.com/search?q=%23" + text.substring(1));
        } else if (text.startsWith("@")) {
            String username = text.substring(1, text.endsWith(":") ? text.length()-1 : text.length());
            return new URL("http://twitter.com/" + username);
        }
        return null;
    }

	@Override
	public void dispose() {
	    lblProfileImage.getImage().dispose();
		super.dispose();
	}
}
